package org.su.mamamiya.swagger.utils;

import com.sun.tools.javac.tree.JCTree;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.su.mamamiya.core.ast.AstProccessor;
import org.su.mamamiya.core.ast.Logger;
import org.su.mamamiya.core.ast.Param;
import org.su.mamamiya.swagger.annotation.SwaggerMethod;
import org.su.mamamiya.swagger.context.SwaggerContext;

import javax.lang.model.element.Element;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by yangchuan on 2019-09-26 17:16
 */
public class SwaggerDocHelper {


    public static void getApi(AstProccessor astProccessor, JCTree.JCMethodDecl jcMethodDecl, String doc, Map<String, Param> params, Element element, SwaggerContext swaggerContext, Logger logger) {
        BufferedReader reader = new BufferedReader(new StringReader(doc));
        StringBuilder sb = new StringBuilder();
        String s,title="";

        JCTree.JCModifiers jcModifiers = jcMethodDecl.mods;
        List<JCTree.JCAnnotation> methodParams = new ArrayList<>();
        JCTree.JCAnnotation methodApi = null;


        try {
            boolean flag = false,first = true;
            while ((s = reader.readLine()) != null) {
                if (s.trim().startsWith("@param")) {

                    flag = true;
                    s = s.trim().substring(7).trim();

                    int index = s.indexOf(" ");
                    if (index < 0) {
                        index = 0;
                    }
                    com.sun.tools.javac.util.List<JCTree.JCExpression> expressions = com.sun.tools.javac.util.List.nil();
                    expressions = expressions.append(
                            astProccessor.assign("value", s.substring(index).trim())
                    );
                    String name = index == 0 ? s : s.substring(0, index);
                    Param param = params.get(name);


                    if (param == null || StringUtils.isEmpty(param.getDataType())
                    || param.getParamType().equals("body") || "form".equals(param.getParamType())) {
                        continue;
                    }

                    expressions = expressions.append(
                            astProccessor.assign("allowMultiple", param.isAllowMultiple())
                    ).append(
                            astProccessor.assign("name", name)
                    ).append(
                            astProccessor.assign("paramType", param.getParamType())
                    ).append(
                            astProccessor.assign("dataType", param.getDataType())
                    ).append(
                            astProccessor.assign("required", param.isRequired())
                    );

                    JCTree.JCAnnotation jcAnnotation = astProccessor.getAnnotation(astProccessor.memberAccess("io.swagger.annotations.ApiImplicitParam"), expressions);

                    methodParams.add(jcAnnotation);

                } else if (s.trim().startsWith("@return")) {

                } else {
                    if (!flag ) {
                        if(first){
                            title = s;
                            first = false;
                        }else{
                            sb.append(s.trim()).append("</br>");
                        }
                    }
                }
            }
            if (methodParams.size() > 0 && element.getAnnotation(ApiImplicitParams.class) == null) {
                com.sun.tools.javac.util.List<JCTree.JCExpression> values = com.sun.tools.javac.util.List.nil();
                for (JCTree.JCAnnotation item : methodParams) {
                    values = values.append(item);
                }

                com.sun.tools.javac.util.List pp = com.sun.tools.javac.util.List.nil();

                if (swaggerContext.isNotParamsNull()) {
                    JCTree.JCNewArray aa = swaggerContext.createApiParams();
                    aa.elems = values;
                    pp = pp.append(astProccessor.assignObj("value", aa));
                } else if (element.getAnnotation(SwaggerMethod.class) != null) {
                    for (JCTree.JCAnnotation annotation : jcModifiers.annotations) {
                        String annotationType = annotation.getAnnotationType().toString();
                        if (annotationType.contains("SwaggerMethod")) {
                            JCTree.JCAssign assign = (JCTree.JCAssign) annotation.args.get(0);
                            JCTree.JCNewArray aa = (JCTree.JCNewArray) assign.rhs;
                            aa.elems = values;
                            pp = pp.append(astProccessor.assignObj("value", aa));
                            break;
                        }
                    }
                }

                JCTree.JCAnnotation jcAnnotation = astProccessor.getAnnotation(astProccessor.memberAccess("io.swagger.annotations.ApiImplicitParams"),
                        pp);

                jcModifiers.annotations = jcModifiers.annotations.append(jcAnnotation);
            }

            if(element.getAnnotation(ApiOperation.class) == null) {
                methodApi = astProccessor.getAnnotation(astProccessor.memberAccess("io.swagger.annotations.ApiOperation"),
                        com.sun.tools.javac.util.List.of(
                                astProccessor.assign("value", title),
                                astProccessor.assign("notes", sb.toString())
                        )
                );
                jcModifiers.annotations = jcModifiers.annotations.append(methodApi);
            }
            jcMethodDecl.mods = jcModifiers;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    public static void setApiTitle(AstProccessor astProccessor, JCTree.JCClassDecl jcClassDecl, String doc, SwaggerContext swaggerContext) {
        BufferedReader reader = new BufferedReader(new StringReader(doc));
        String s;
        try {
            while ((s = reader.readLine()) != null) {
                if (StringUtils.isNotBlank(s)) {
                    s = s.trim();
                    com.sun.tools.javac.util.List<JCTree.JCExpression> expressions = com.sun.tools.javac.util.List.of(
                            astProccessor.assign("tags", s)
                    );
                    JCTree.JCAnnotation jcAnnotation = astProccessor.getAnnotation(astProccessor.memberAccess("io.swagger.annotations.Api"), expressions);

                    JCTree.JCModifiers jcModifiers = jcClassDecl.getModifiers();
                    jcModifiers.annotations = jcModifiers.annotations.append(jcAnnotation);


                    if (swaggerContext.isNotResponsesNull()) {
                        expressions = com.sun.tools.javac.util.List.of(
                                astProccessor.assignObj("value", swaggerContext.createApiResponses())
                        );
                        jcAnnotation = astProccessor.getAnnotation(astProccessor.memberAccess("io.swagger.annotations.ApiResponses"), expressions);
                        jcModifiers.annotations = jcModifiers.annotations.append(jcAnnotation);
                    }
                    jcClassDecl.mods = jcModifiers;

                    break;
                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }


    public static void setParamApi(AstProccessor astProccessor, JCTree.JCMethodDecl methodDecl, String doc, Map<String, Param> params, Element item, SwaggerContext swaggerContext, Logger logger) {
    }
}
